#define _GNU_SOURCE
#include "app_device.h"
#include "log/log.h"
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include "app_pool.h"
#include "app_mqtt.h"
#include "app_common.h"

static Device *device;

static int  app_device_write_task(void *){
    char chars_buffer[256];
    int chars_len=app_buffer_read(device->down_buffer, chars_buffer, 256);
    if(chars_len<=0){
        log_info("app_device_write_task: chars_len=%d", chars_len);
        return -1;
    }

    // 200ms between two writes
    unsigned long long time_diff=app_common_getCurrentTime()-device->last_write_time;
    if(time_diff<200){
        usleep((200-time_diff)*1000);
    }
    int write_len= write(device->fd, chars_buffer, chars_len);
    if(write_len !=chars_len){
        log_info("app_device_write_task: write_len=%d", write_len);
        return -1;
    }
    device->last_write_time=app_common_getCurrentTime();
    log_info("app_device_write_task: write_len=%d", write_len);
    return 0;
}
/**
 * 设备接收远程消息的回调函数
 */
static int receive_msg_callback(char *json)
{
    char chars_buffer[256];
    int chars_len=app_message_jsonToChars(json, chars_buffer, 256);
    if(chars_len<=0){
        return -1;
    }

    //bluetooh or other device
    //todo


    if(device->pre_write!=NULL){
       chars_len= device->pre_write(chars_buffer, chars_len);
    }
    int result=app_buffer_write(device->down_buffer, chars_buffer, chars_len);
    log_info("将数据写入下行缓冲区成功!data = %.*s", chars_len, device->down_buffer);
    if(result==-1){
        return -1;
    }

    app_pool_registerTask(app_device_write_task, NULL);
    return 0;
}
/**
* 初始化设备
*/
Device *app_device_init(char *filename){
    device = (Device *)malloc(sizeof(Device));

    if (device != NULL) {
        device->filename = filename;
        device->fd = open(filename, O_RDWR | O_APPEND, 0666);
        device->up_buffer = app_buffer_init(1024);
        device->down_buffer = app_buffer_init(1024);
        // device->read_thread=NULL;
        device->is_running=0;
        device->post_read=NULL;
        device->pre_write=NULL;

        
        app_pool_init(5);
        app_mqtt_init();
        app_mqtt_registerRecvCallback(receive_msg_callback);
        
        return device;
    }
}

//发送数据到MQTT 服务器
static  int app_device_send_task(void *){
    char chars_buffer[256];
    int read_len= app_buffer_read(device->up_buffer, chars_buffer, 256);
    if(read_len==-1){
        return -1;
    }
    //buff to json
    char *json_str= app_message_charsToJson(chars_buffer, read_len);
    int result=app_mqtt_send(json_str);
    if(result==-1){
        log_info("app_device_send_task: app_mqtt_send failed");
        return -1;
    }
    free(json_str);
    log_info("app_device_send_task: app_mqtt_send success json=%s", json_str);
    return 0;
}
//read bluetooth  data to buffer 
static void *app_device_read_task(void *){
    while(device->is_running==1){
       char data_buffer[256];
       ssize_t data_len= read(device->fd, data_buffer, 256);
       if(data_len>0 && device->post_read!=NULL){
          data_len=  device->post_read(data_buffer, data_len);
            
       }
       if(data_len>0){
         int result= app_buffer_write(device->up_buffer, data_buffer, data_len);
         if(result==-1){
             log_info("app_device_read_task: app_buffer_write failed");
             return NULL;
         }else{
             log_info("app_device_read_task: app_buffer_write success");
             app_pool_registerTask(app_device_send_task, NULL);
         }
       }
    }
    return NULL;
}
/**
* 启动设备的读线程
*/
int app_device_start(){
    if(device->is_running==1){
        log_info("app_device_start: device is running");
        return 0;
    }
    device->is_running=1;

    pthread_create(&device->read_thread, NULL, app_device_read_task, NULL);
    
    return 0;
}

/**
* 销毁设备
*/
void app_device_destroy(){
    if (device != NULL) { 
        device->is_running=0;
    
        close(device->fd);
        
        app_buffer_free(device->up_buffer);
        app_buffer_free(device->down_buffer);

        pthread_cancel(device->read_thread);
        app_mqtt_close();
        app_pool_close();
        free(device);
    }
}


